package com.nf.android.common.utils;

import android.app.Activity;
import android.database.Cursor;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import android.text.TextUtils;


import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

public class FileUtil {

	/*文件的根目录*/
	private final static String PATH_ROOT = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/com.nf.android.eoa/files";

	private FileUtil() {
	}

	/**
	 * The number of bytes in a kilobyte.
	 */
	public static final long ONE_KB = 1024;

	/**
	 * The number of bytes in a megabyte.
	 */
	public static final long ONE_MB = ONE_KB * ONE_KB;

	/**
	 * The number of bytes in a gigabyte.
	 */
	public static final long ONE_GB = ONE_KB * ONE_MB;

	/**
	 * The UTF-8 character set, used to decode octets in URLs.
	 */
	private static final Charset UTF8 = Charset.forName("UTF-8");

	/**
	 * 根据文件名获取扩展名
	 * 
	 * @param filename
	 *            文件名
	 * @return 文件扩展名
	 */
	public static String getFileExtensionFromName(String filename) {
		if (filename == null) {
			return null;
		}
		int index = indexOfExtension(filename);
		if (index == -1) {
			return "";
		} else {
			return filename.substring(index + 1);
		}
	}

	private static int indexOfExtension(String filename) {
		if (filename == null) {
			return -1;
		}
		int extensionPos = filename.lastIndexOf(".");
		int lastSeparator = filename.lastIndexOf("/");
		return (lastSeparator > extensionPos ? -1 : extensionPos);
	}

	/**
	 * Returns the file extension or an empty string if there is no extension.
	 * This method is a convenience method for obtaining the extension of a url
	 * and has undefined results for other Strings.
	 * 
	 * @param url
	 * @return The file extension of the given url.
	 */
	public static String getFileExtensionFromUrl(String url) {
		if (url != null && url.length() > 0) {
			int query = url.lastIndexOf('?');
			if (query > 0) {
				url = url.substring(0, query);
			}
			int filenamePos = url.lastIndexOf('/');
			String filename = 0 <= filenamePos ? url.substring(filenamePos + 1)
					: url;

			// if the filename contains special characters, we don't
			// consider it valid for our matching purposes:
			if (filename.length() > 0
					&& Pattern.matches("[a-zA-Z_0-9\\.\\-\\(\\)]+", filename)) {
				int dotPos = filename.lastIndexOf('.');
				if (0 <= dotPos) {
					return filename.substring(dotPos + 1);
				}
			}
		}

		return "";
	}

	public static String getFileExtensionFromSource(byte[] picHeader) {
		String picExtendName = null;

		if (picHeader.length >= 2 && (picHeader[0] == 66)
				&& (picHeader[1] == 77)) {
			// header bytes contains BM?
			picExtendName = "BMP";
		} else if (picHeader.length >= 4 && (picHeader[1] == 80)
				&& (picHeader[2] == 78) && (picHeader[3] == 71)) {
			// header bytes contains PNG?
			picExtendName = "PNG";
		} else if (picHeader.length >= 6 && (picHeader[0] == 71)
				&& (picHeader[1] == 73) && (picHeader[2] == 70)
				&& (picHeader[3] == 56)
				&& ((picHeader[4] == 55) || (picHeader[4] == 57))
				&& (picHeader[5] == 97)) {
			// header bytes contains GIF87a or GIF89a?
			picExtendName = "GIF";
		} else if (picHeader.length >= 10 && (picHeader[6] == 74)
				&& (picHeader[7] == 70) && (picHeader[8] == 73)
				&& (picHeader[9] == 70)) {
			// header bytes contains JFIF?
			picExtendName = "JPG";
		}

		return picExtendName;
	}

	public static boolean isGif(String filePath) {
		boolean isGif = false;
		if (TextUtils.isEmpty(filePath)) {
			return isGif;
		}

		File file = new File(filePath);
		if (file.exists() && file.isFile()) {
			FileInputStream fis = null;
			try {
				fis = new FileInputStream(file);
				StringBuilder head = new StringBuilder("");
				for (int i = 0; i < 6; i++) {
					head.append((char) fis.read());
				}
				if (head.indexOf("GIF") == 0) {
					isGif = true;
				}
			} catch (FileNotFoundException e) {
				Log.e("isGif", e.toString());
			} catch (IOException e) {
				Log.e("isGif", e.toString());
			} finally {
				if (fis != null) {
					try {
						fis.close();
					} catch (IOException e) {
					}
				}
			}
		}

		return isGif;
	}

	public static byte[] readFileToByteArray(String filePath) {
		if (TextUtils.isEmpty(filePath)) {
			return null;
		}
		File file = new File(filePath);

		return readFileToByteArray(file);
	}

	public static byte[] readFileToByteArray(File file) {
		byte[] fileBytes = new byte[(int) file.length()];

		FileInputStream fis = null;
		try {
			fis = new FileInputStream(file);
			int offset = 0;
			int count = (int) file.length();
			int temp = 0;

			while ((temp = fis.read(fileBytes, offset, count)) > 0) {
				offset += temp;
				count -= temp;
			}
		} catch (FileNotFoundException e) {
			Log.e("readFile", e.toString());
		} catch (IOException e) {
			Log.e("readFile", e.toString());
		} catch (Exception e) {
			Log.e("readFile", e.toString());
		} finally {
			if (fis != null) {
				try {
					fis.close();
				} catch (IOException e) {
					Log.e("readFile", e.toString());
				}
			}
		}

		return fileBytes;
	}

	public static FileInputStream openInputStream(File file) throws IOException {
		if (file.exists()) {
			if (file.isDirectory()) {
				throw new IOException("File '" + file
						+ "' exists but is a directory");
			}
			if (file.canRead() == false) {
				throw new IOException("File '" + file + "' cannot be read");
			}
		} else {
			throw new FileNotFoundException("File '" + file
					+ "' does not exist");
		}
		return new FileInputStream(file);
	}

	public static String byteCountToDisplaySize(long size) {
		String displaySize;

		if (size / ONE_GB > 0) {
			displaySize = String.format("%1$.1f GB", (float) size / ONE_GB);
		} else if (size / ONE_MB > 0) {
			displaySize = String.format("%1$.1f MB", (float) size / ONE_MB);
		} else if (size / ONE_KB > 0) {
			displaySize = String.format("%1$.1f KB", (float) size / ONE_KB);
		} else {
			displaySize = String.valueOf(size) + " Bytes";
		}
		return displaySize;
	}

	public static long sizeOf(File file) {

		if (!file.exists()) {
			throw new IllegalArgumentException(file + " does not exist");
		}

		if (file.isDirectory()) {
			return sizeOfDirectory(file);
		} else {
			return file.length();
		}

	}

	public static long sizeOfDirectory(File directory) {
		if (!directory.exists()) {
			String message = directory + " does not exist";
			throw new IllegalArgumentException(message);
		}

		if (!directory.isDirectory()) {
			String message = directory + " is not a directory";
			throw new IllegalArgumentException(message);
		}

		long size = 0;

		File[] files = directory.listFiles();
		if (files == null) { // null if security restricted
			return 0L;
		}
		for (File file : files) {
			size += sizeOf(file);
		}

		return size;
	}

	public static File toFile(URL url) {
		if (url == null || !"file".equalsIgnoreCase(url.getProtocol())) {
			return null;
		} else {
			String filename = url.getFile().replace('/', File.separatorChar);
			filename = decodeUrl(filename);
			return new File(filename);
		}
	}

	/**
	 * Decodes the specified URL as per RFC 3986, i.e. transforms
	 * percent-encoded octets to characters by decoding with the UTF-8 character
	 * set. This function is primarily intended for usage with
	 * {@link java.net.URL} which unfortunately does not enforce proper URLs. As
	 * such, this method will leniently accept invalid characters or malformed
	 * percent-encoded octets and simply pass them literally through to the
	 * result string. Except for rare edge cases, this will make unencoded URLs
	 * pass through unaltered.
	 * 
	 * @param url
	 *            The URL to decode, may be <code>null</code>.
	 * @return The decoded URL or <code>null</code> if the input was
	 *         <code>null</code>.
	 */
	static String decodeUrl(String url) {
		String decoded = url;
		if (url != null && url.indexOf('%') >= 0) {
			int n = url.length();
			StringBuffer buffer = new StringBuffer();
			ByteBuffer bytes = ByteBuffer.allocate(n);
			for (int i = 0; i < n;) {
				if (url.charAt(i) == '%') {
					try {
						do {
							byte octet = (byte) Integer.parseInt(
									url.substring(i + 1, i + 3), 16);
							bytes.put(octet);
							i += 3;
						} while (i < n && url.charAt(i) == '%');
						continue;
					} catch (RuntimeException e) {
						// malformed percent-encoded octet, fall through and
						// append characters literally
					} finally {
						if (bytes.position() > 0) {
							bytes.flip();
							buffer.append(UTF8.decode(bytes).toString());
							bytes.clear();
						}
					}
				}
				buffer.append(url.charAt(i++));
			}
			decoded = buffer.toString();
		}
		return decoded;
	}

	/**
	 * 通过uri获取文件时机路径
	 * 
	 * @param mContext
	 * @param fileUrl
	 * @return
	 */
	public static String getAbsoluteImagePath(Activity mContext, Uri fileUrl) {
		String fileName = null;
		Uri filePathUri = fileUrl;
		if (fileUrl != null) {
			if (fileUrl.getScheme().toString().compareTo("content") == 0) // content://开头的uri
			{
				String[] proj = {MediaStore.Images.ImageColumns.DATA};
				Cursor cursor = mContext.getContentResolver().query(fileUrl,
						proj, null, null, null);
				if (cursor != null && cursor.moveToFirst()) {
					int column_index = cursor
							.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.DATA);
					fileName = cursor.getString(column_index); // 取出文件路径
					cursor.close();
				}
			} else if (fileUrl.getScheme().compareTo("file") == 0) // file:///开头的uri
			{
				fileName = filePathUri.toString();
				fileName = filePathUri.toString().replace("file://", ""); // 替换file://
//				if (!fileName.startsWith("/mnt")) { // 加上"/mnt"头
//					fileName += "/mnt";
//				}
			}
		}
		return fileName;
	}

	/**
	 * 通过uri获取文件的各种属性
	 *
	 * @param mContext
	 * @param fileUrl
	 * @return
	 */
	public static String[] getExtraInfo(Activity mContext, Uri fileUrl, String proj[]) {
		String ImageInfo[] = new String[proj.length];
		if (fileUrl != null) {
			if (fileUrl.getScheme().toString().compareTo("content") == 0) // content://开头的uri
			{
				Cursor cursor = mContext.getContentResolver().query(fileUrl, proj, null, null, null);
				if (cursor != null && cursor.moveToFirst()) {
					for( int i = 0 ; i < proj.length ; i ++ ) {
						int column_index = cursor.getColumnIndexOrThrow( proj[i] );
						ImageInfo[i] = cursor.getString(column_index); // 取出指定的信息
					}
					cursor.close();
				}
			}
		}
		return ImageInfo;
	}

	public static void delFile(String path, String fileName) {
		try {
			File file=new File(path+"/"+fileName);
			if(file.exists() && file.isFile())
				file.delete();
		}catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void delFile(String fileurl) {
		try {
			File file=new File(fileurl);
			if(file.exists() && file.isFile())
				file.delete();
		}catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static String getRootPath() {
		return PATH_ROOT;
	}

	public static void delFolder(String folderPath) {
		try {
			delAllFile(folderPath); //删除完里面所有内容
			String filePath = folderPath;
			filePath = filePath.toString();
			java.io.File myFilePath = new java.io.File(filePath);
			myFilePath.delete(); //删除空文件夹
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private static boolean delAllFile(String path) {
		boolean flag = false;
		File file = new File(path);
		if (!file.exists()) {
			return flag;
		}
		if (!file.isDirectory()) {
			return flag;
		}
		String[] tempList = file.list();
		File temp = null;
		for (int i = 0; i < tempList.length; i++) {
			if (path.endsWith(File.separator)) {
				temp = new File(path + tempList[i]);
			} else {
				temp = new File(path + File.separator + tempList[i]);
			}
			if (temp.isFile()) {
				temp.delete();
			}
			if (temp.isDirectory()) {
				delAllFile(path + "/" + tempList[i]);//先删除文件夹里面的文件
				delFolder(path + "/" + tempList[i]);//再删除空文件夹
				flag = true;
			}
		}
		return flag;
	}

	/**
	 * 获取路径下的所有文件/文件夹
	 * @param directoryPath 需要遍历的文件夹路径
	 * @param isAddDirectory 是否将子文件夹的路径也添加到list集合中
	 * @return
	 */
	public static List<String> getAllFile(String directoryPath, boolean isAddDirectory) {
		List<String> list = new ArrayList<String>();
		File baseFile = new File(directoryPath);
		if (baseFile.isFile() || !baseFile.exists()) {
			return list;
		}
		File[] files = baseFile.listFiles();
		for (File file : files) {
			if (file.isDirectory()) {
				if(isAddDirectory){
					list.add(file.getAbsolutePath());
				}
				list.addAll(getAllFile(file.getAbsolutePath(),isAddDirectory));
			} else {
				list.add(file.getAbsolutePath());
			}
		}
		return list;
	}

	public static String byteCountToDisplaySize(String size) {

		if (TextUtils.isEmpty(size)) {
			return "";
		}

		long originalSize = Long.parseLong(size);
		String displaySize;

		if (originalSize / ONE_GB > 0) {
			displaySize = String.format("%1$.1f GB", (float) originalSize / ONE_GB);
		} else if (originalSize / ONE_MB > 0) {
			displaySize = String.format("%1$.1f MB", (float) originalSize / ONE_MB);
		} else if (originalSize / ONE_KB > 0) {
			displaySize = String.format("%1$.1f KB", (float) originalSize / ONE_KB);
		} else {
			displaySize = String.valueOf(size) + " B";
		}
		return displaySize;
	}
}
